
/* This this the only include needed in your code .*/
#include "femtoos_code.h"
#include "serial.h"
#include "adc.h"

#ifdef OPT_SERIAL_SUPPORT

//---------------------------
// Definition
//---------------------------
#define ELEMENTS_NUM(x) (sizeof(x)/sizeof(x[0]))
#define MAX_CMD_LEN 20

//---------------------------
// Global variable Declaration
//---------------------------
typedef struct
{
    /*int (*closefunc)();*/
	char (*testfunc)(char*);
}functions_s;
static functions_s functionality[]	=
{
	{showHelp},
	{showVersion},
	{showAdcVoltage}
};
static char cmdName1[] PROGMEM = "help";
static char cmdName2[] PROGMEM = "show_version";
static char cmdName3[] PROGMEM = "show_adc_input";
static PGM_P string_table[] PROGMEM = 
{
	cmdName1,
	cmdName2,
	cmdName3
}; 
static char string0[] PROGMEM = "\r\nWelcome to FemtoOS command line tool Ver. ";
static char string1[] PROGMEM = "\r\n";
static char string2[] PROGMEM = "This version modified by Imam Sumarsono\r\n";
static char string3[] PROGMEM = "============================================\r\n";
static char string4[] PROGMEM = "This is list of supported command :\r\n";
static char string5[] PROGMEM = "\r\nVersion Information";
static char string6[] PROGMEM = "\r\nMain Version : ";
static char string7[] PROGMEM = "\r\nFemto OS Version : ";
static char string8[] PROGMEM = "\r\nADC input voltage";
static char string9[] PROGMEM = "\r\n- Input Voltage ADC ";
static PGM_P string_table2[] PROGMEM = 
{
	string0,
	string1,
	string2,
	string3,
	string4,
	string5,
	string6,
	string7,
	string8,
	string9
}; 

//---------------------------
// Functions
//---------------------------
void USART_Transmit( unsigned char data )
{
	/* Wait for empty transmit buffer */
	while ( !( UCSRA & (1<<UDRE)) )
	{
		taskDelayFromNow(1);
	}
	/* Put data into buffer, sends the data */
	UDR = data;
}
unsigned char USART_Receive()
{
    unsigned char cInput;
    /* Wait for data to be received */
    while ( !(UCSRA & (1<<RXC)) )
	{
	    taskDelayFromNow(1);
	}
    /* Get and return received data from buffer */
	cInput = UDR;
	USART_Transmit(cInput);
    return cInput;
}
void iprintf(char *sdata)
{
    char c=0;
    while(*(sdata+c)!=0)
	{ 
	    USART_Transmit(*(sdata+c));
		c++;
	}
}
void USART_gets(char *stringGet)
{
	unsigned char cdata;
	unsigned int  counter=0;
	cdata = USART_Receive();
	while( cdata != 0x0d)
	{
		if(cdata==0x08&&counter>0)
			counter--;
		else
			*(stringGet+counter++)=cdata;
		cdata = USART_Receive();
		if(counter>=20)
			counter=0;
	}
	*(stringGet+counter)=0;
}
void ShowWMessage()
{
	char buffer[50];	
	strcpy_P(buffer, (PGM_P)pgm_read_word(&string_table2[0]));
	iprintf(buffer);
	iprintf(MAIN_VER);
	strcpy_P(buffer, (PGM_P)pgm_read_word(&string_table2[1]));
	iprintf(buffer);
	strcpy_P(buffer, (PGM_P)pgm_read_word(&string_table2[2]));
	iprintf(buffer);
	strcpy_P(buffer, (PGM_P)pgm_read_word(&string_table2[3]));
	iprintf(buffer);

}
void parse_command(char *sInputCmd, char *sNextCommand)
{
    char ccount=0;
    while(*(sInputCmd+ccount) != 0)
    {
    	if( *(sInputCmd+ccount) == ' ')
    	{
    	    *(sInputCmd+ccount)=0;
    	    strcpy(sNextCommand,sInputCmd+ccount+1);
    	}
		ccount++;
    }
}
void ExecCmd() 
{
	char sInputCmd[MAX_CMD_LEN];
	char *sCommand;	
	char callParams[5];
    char buffer[MAX_CMD_LEN];
	char index;
	
	iprintf("\r\nCLI> ");
	USART_gets(sInputCmd);
	parse_command(sInputCmd,callParams);
	for(index = 0; index < ELEMENTS_NUM(functionality); ++index)
	{
    	   strcpy_P(buffer, (PGM_P)pgm_read_word(&string_table[index]));
		   if(strcmp(buffer, sInputCmd) == 0)
		   {
		   	   functionality[index].testfunc(callParams);	
			   break;
		   }
	}	
}
static char showHelp(){
	char index;
	char buffer[50];	
	strcpy_P(buffer, (PGM_P)pgm_read_word(&string_table2[4]));
	iprintf(buffer);
	for(index = 0; index < ELEMENTS_NUM(functionality); ++index)
	{
    	strcpy_P(buffer, (PGM_P)pgm_read_word(&string_table[index]));		
		iprintf("- ");
		iprintf(buffer);
		iprintf("\r\n");
	}	
	return 0;
}
static char showVersion()
{
	char buffer[50];	
	strcpy_P(buffer, (PGM_P)pgm_read_word(&string_table2[5]));
	iprintf(buffer);
	strcpy_P(buffer, (PGM_P)pgm_read_word(&string_table2[6]));
	iprintf(buffer);
	iprintf(MAIN_VER);
	strcpy_P(buffer, (PGM_P)pgm_read_word(&string_table2[7]));
	iprintf(buffer);
	iprintf(FOS_VER);
	return 0;
}

void InitSerial()
{

    // CPU Frequency : 8 MHz
	// USART initialization
	// Communication Parameters: 8 Data, 1 Stop, No Parity
	// USART Receiver: On
	// USART Transmitter: On
	// USART Mode: Asynchronous
	// USART Baud Rate: 115200 (Double Speed Mode)
	UCSRA=0x02;
	UCSRB=0x18; 
	UCSRC=0x86;
	UBRRH=0x00;
	UBRRL=0x08;
}
#ifdef OPT_ADC_SUPPORT

static void printAdcVoltage(unsigned char adcInput)
{
	unsigned int iVin;
	char sAdcV[5]="0.00";
        unsigned int count=0;
        adcInput=1;
	/*iVin = (read_adc(adcInput) * ADC_VREF * 100)/1024;*/
	iVin = (read_adc(adcInput) * ADC_VREF * 10)/102;
	/*convert to string*/
	while(iVin>=100)
	{
	    iVin-=100;
	    count++;
	}
	sAdcV[0]=count+0x30;
	count=0;
	while(iVin>=10)
	{
	    iVin-=10;
	    count++;
	}
	sAdcV[2]=count+0x30;
	sAdcV[3]=iVin+0x30;
	sAdcV[4]=0;
	iprintf(sAdcV);
}
static char showAdcVoltage(char *param)
{
	char buffer[50];	
	char ccount=0;
	
	if(*param<'8' && *param>='0')
	{
		strcpy_P(buffer, (PGM_P)pgm_read_word(&string_table2[8]));
		iprintf(buffer);
		strcpy_P(buffer, (PGM_P)pgm_read_word(&string_table2[9]));
		iprintf(buffer);
		iprintf(param);
		iprintf(" : ");
        printAdcVoltage(*param - 0x30);
	}
	else if (*param=='9')
	{
		strcpy_P(buffer, (PGM_P)pgm_read_word(&string_table2[8]));
		iprintf(buffer);
		for (ccount=0;ccount<8;ccount++)
		{
			strcpy_P(buffer, (PGM_P)pgm_read_word(&string_table2[9]));
			iprintf(buffer);
			USART_Transmit(ccount+0x30);
			iprintf(" : ");
			printAdcVoltage(ccount);
		}
	}
	return RESULT_OK;
}
#else /*OPT_ADC_SUPPORT*/

static char showAdcVoltage(char *param){return RESULT_NG;}

#endif /*OPT_ADC_SUPPORT*/

#else /*OPT_SERIAL_SUPPORT */

void InitSerial(){}
void ExecCmd(){}
void ShowWMessage(){}

#endif /*OPT_SERIAL_SUPPORT */

